#include <iostream>
#include <ctime>
#include "ThreadPool.hpp"   // 线程池头文件
#include "Task.hpp"         // 任务类头文件

// 声明自旋锁变量（目前未使用）
// 自旋锁特点：忙等待，适用于临界区很小的情况
pthread_spinlock_t slock;

int main()
{
    // 自旋锁的初始化和销毁（已注释掉）
    // pthread_spin_init(&slock, 0);    // 初始化自旋锁，第二个参数0表示线程内使用
    // pthread_spin_destroy(&slock);     // 销毁自旋锁

    // 注释提出的问题：如果获取单例对象的时候，也是多线程获取的呢？
    // 这个问题涉及到单例模式的线程安全性
    // 需要在GetInstance()中使用双检锁或其他线程安全的实现方式

    // 启动提示信息
    std::cout << "process runn..." << std::endl;
    sleep(3);    // 程序启动后等待3秒，方便观察启动过程

    // 两种创建线程池的方式：
    // 1. 直接创建（已注释）：
    // ThreadPool<Task> *tp = new ThreadPool<Task>(5);  // 创建5个线程的线程池
    
    // 2. 使用单例模式（当前使用）：
    ThreadPool<Task>::GetInstance()->Start();  // 获取线程池实例并启动

    // 初始化随机数种子
    // 使用当前时间和进程ID异或，增加随机性
    srand(time(nullptr) ^ getpid());

    // 主循环：持续生成任务
    while(true)
    {
        // 1. 构建任务
        int x = rand() % 10 + 1;    // 生成1-10的随机数作为第一个操作数
        usleep(10);                 // 短暂休眠，增加随机数的离散性
        int y = rand() % 5;         // 生成0-4的随机数作为第二个操作数
        // 从操作符数组中随机选择一个操作符
        char op = opers[rand()%opers.size()];

        // 创建任务对象
        Task t(x, y, op);
        // 将任务提交给线程池
        ThreadPool<Task>::GetInstance()->Push(t);
        
        // 2. 交给线程池处理
        // 输出任务信息，表示主线程创建了什么任务
        std::cout << "main thread make task: " << t.GetTask() << std::endl;

        // 休眠1秒，控制任务生成速率
        sleep(1);
    }
}